package com.sinodata.bsm.cicp.collector.file;

import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.Collector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.CollectorUtil;
import com.sinodata.bsm.cicp.util.CommandReader;
import com.sinodata.bsm.cicp.util.FileAttribute;
import com.sinodata.bsm.common.utils.FileUtil;
import com.sinodata.bsm.common.vo.ResPropertyValue;

/**
 * 
 * <p>
 * Description: (已废弃)日志文件内容监控
 * 1:该监控被 LogFileCollector替代 本监控程序不再使用
 * </p>
 *
 * @author wangyazhou
 * @version 1.0
 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-8-3 20:32:44        wangyazhou     1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class FileContentCollector extends Collector {

    private static Logger logger = Logger.getLogger(FileContentCollector.class);

    public FileContentCollector() {

    }

    /*
     * (non-Javadoc)
     * @see com.sinodata.bsm.cicp.collector.Collector#collect(java.lang.String)
     */
    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        String filePath = this.getParamMap().get("FilePath");//文件路径
        String fileName = this.getParamMap().get("FileFormat");//文件名称
        String errFlag = this.getParamMap().get("ErrorFlog");//错误标识
        if (errFlag.equalsIgnoreCase("N/A")) {
            errFlag = "";
        }
        FileAttribute currentAttribute = CollectorUtil.getNewestRemoteFileByPattern(filePath, null, fileName, ip);
        if (currentAttribute == null) {
            return null;
        }
        fileName = currentAttribute.name;
        String fullFileName = getFullFileName(filePath, fileName);
        String tmpFileName = getTmpFileName(fullFileName, errFlag, ip);
        FileAttribute lastAttribute = (FileAttribute) FileUtil.readObjFromFile(tmpFileName);

        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();

        //fullFileName = getFullFileName(filePath, fileName);
        if (lastAttribute != null) {
            if (!currentAttribute.name.equals(lastAttribute.name)) {
                long position = 0;
                values = readFile(fileName, fullFileName, position, errFlag, ip);
            } else if (currentAttribute.size > lastAttribute.size) {
                long position = lastAttribute.size;
                values = readFile(fileName, fullFileName, position, errFlag, ip);
            } else if (currentAttribute.size < lastAttribute.size) {
                values = readFile(fileName, fullFileName, 0, errFlag, ip);
            } else {
                return null;//**此处返回null有问题 by liu**，此处是相等，应返回文件名，错误内容为空串
            }
        }
        // 记录文件位置
        if (lastAttribute == null) {
            long position = 0;
            values = readFile(fileName, fullFileName, position, errFlag, ip);
        }
        if (lastAttribute == null || !lastAttribute.equals(currentAttribute)) {
            try {
                logger.info(">>>>>>write to temp file:" + tmpFileName);
                FileUtil.forceWriteObjToFile(tmpFileName, currentAttribute, false);
            } catch (Exception e) {
                logger.error("failed to call " + this.getClass().getName() + ".collect", e);
                throw new CollectorException(e);
            }
        }
        return values;
    }

    /**
     * 获取全文件 文件名
     * 
     * @param path
     * @param fileName
     * @return
     */
    private String getFullFileName(String path, String fileName) {
        path = path.trim();
        if (path.endsWith("/")) {
            return path + fileName;
        } else {
            return path + "/" + fileName;
        }
    }

    /**
     * 获取临时文件 文件名
     * 
     * @param fileName
     * @param errFlag
     * @param ip
     * @return
     */
    private String getTmpFileName(String fileName, String errFlag, String ip) {
        String path = "tmp/";
        StringBuffer buffer = new StringBuffer();
        buffer.append(ip).append("_").append(fileName).append("_").append(errFlag);
        return path + FileUtil.validateFileName(buffer.toString());
    }

    /**
     * 从文件的某个位置开始读，直至文件结束
     * 
     * @param fileName
     * @param readStart
     * @param ip
     * @return
     * @throws CollectorException 
     */
    private List<ResPropertyValue> readFile(String fileName, String fullFileName, long readStart, String filterPattern, String ip) throws CollectorException {
        BufferedReader reader = null;
        String cmd = "filter -f " + fullFileName + " -s " + readStart;
        if (filterPattern != null) {
            cmd = cmd + " -p '" + filterPattern + "'";
        }
        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();
        String[] propMetas = getPropMeta();
        try {
            reader = CommandReader.getReader(ip, cmd, 0, 0);
            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.length() == 0) {
                    continue;
                }
                ResPropertyValue propertyValueX = new ResPropertyValue();
                ResPropertyValue.PropValue[] propValues = new ResPropertyValue.PropValue[propMetas.length];
                propValues[0] = ResPropertyValue.createPropValue(fullFileName, propMetas[0]);
                propValues[1] = ResPropertyValue.createPropValue(line, propMetas[1]);
                propertyValueX.setValues(propValues);
                values.add(propertyValueX);
            }
            return values;
        } catch (Exception e) {
            logger.error("failed to call " + this.getClass().getName() + ".readFile", e);
            throw new CollectorException(e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception ex) {
                    logger.error("failed to call " + this.getClass().getName() + ".readFile", ex);
                    throw new CollectorException(ex);
                }
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see com.sinodata.bsm.cicp.collector.Collector#getParamMeta()
     */
    @Override
    public String[] getParamMeta() {
        return new String[] { "FilePath", "FileFormat", "ErrorFlog" };
    }

    /*
     * (non-Javadoc)
     * @see com.sinodata.bsm.cicp.collector.Collector#getPropMeta()
     */
    @Override
    public String[] getPropMeta() {
        return new String[] { "$1", "$2" };
    }

}